﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.IO;


namespace MotivLogger
{
    public class TelnetLog : ILogMethod
    {
        public  List<Thread> ClientsThreads;
        private Object tlockObj;
        private TcpListener listen;
        public  Thread serverthread;
        private bool work;
        private List<TcpClient> Clients;
        private Stream s;
        private List<SynchQueue<string>> messagequeues;
        int listeners;
        public TelnetLog() 
        {
            this.tlockObj = new Object();
            ClientsThreads = new List<Thread>();
            Clients = new List<TcpClient>();
            listen = new TcpListener(System.Net.IPAddress.Parse("127.0.0.1"), 23);
            serverthread = new Thread(DoListen);
            serverthread.Start();
            messagequeues = new List<SynchQueue<string>>(5);
            listeners = 0;
            work = true;
        }
        public void Log(MotivLogger.LogLevels Level, string Message, string Actor)
        {
            string message = LoggerBase.BuildLogRecord(Level, Message, Actor);
            if (listeners > 0)
            {
                lock(tlockObj){
                    foreach (SynchQueue<string> q in messagequeues)
                    q.Enqueue(message);
                }
            }
        }

        private void DoListen(){   
            listen.Start(); //  Костыль -_- поправить!
            listen.Stop();
            listen.Start();
            while (work)
            {
                try
                {
                    TcpClient client = listen.AcceptTcpClient();
                    Clients.Add(client);
                    Thread clientThread = new Thread(new ParameterizedThreadStart(DoClient)) { IsBackground = true };
                    ClientsThreads.Add(clientThread);
                    clientThread.Start(client);
                }
                catch { }

            }
        }

        private void DoClient(object client)
        {
            int num = 0;
            lock (tlockObj)
            {
                num = listeners;
                listeners++;
                messagequeues.Add(new SynchQueue<string>(10));
            }
            TcpClient tClient = (TcpClient)client;
            while (work)
            {
                if (!tClient.Connected)
                {
                    tClient.Close();
                    Thread.CurrentThread.Abort();
                }
                 s = tClient.GetStream();
                string r = "";
                messagequeues[num].Dequeue(out r);
                r += "\n";
                byte[] buf = Encoding.UTF8.GetBytes(r);
                lock (tlockObj) {
                    Thread.Sleep(100);
                    try
                    {
                        if (s.CanWrite) s.Write(buf, 0, buf.Length);
                    }
                    catch { }
                    
                }
                
                Thread.Sleep(50);
            }
        }
        public void Stop()
        {
            work = false;
            try
            {
                listen.Stop();
                foreach(var client in Clients)
                    client.Close();
                foreach (var clientthread in ClientsThreads)
                    clientthread.Abort();
                s.Close();
                serverthread.Abort();
            }
            catch { }
        }
    }
}
